package exp4;

import javax.swing.*;
import java.awt.*;
import java.util.Random;

public class Exp4_4 {
	int N = 300;
	int K = 3;

	double[][] points = new double[N][2];
	double[][] centers = new double[K][2];
	double[][] distances = new double[N][K];
	int[] kinds = new int[N];

	JFrame win;
	final int WIN_HEIGHT = 420;
	final int WIN_WIDTH = 600;

	final String[] MARKER_TEXTS = { "x", "o", "+" };
	final Color[] MARKER_COLORS = { Color.RED, Color.MAGENTA, Color.BLUE };

	void generatePoints() {
		double[][] ps = { { 300, 50 }, { 480, 300 }, { 120, 200 } };
		Random r = new Random();
		int p;
		for (int i = 0; i < N; i++) {
			p = r.nextInt(K);
			points[i][0] = ps[p][0] + (r.nextBoolean() ? r.nextInt(100) : -r.nextInt(100));
			points[i][1] = ps[p][1] + (r.nextBoolean() ? r.nextInt(50) : -r.nextInt(50));
		}
	}

	void initCenters() {
		for (int i = 0; i < K; i++) {
			centers[i][0] = points[i * N / K][0];
			centers[i][1] = points[i * N / K][1];
		}
	}

	void assignPoints() {
		double dx, dy;
		double min;
		for (int i = 0; i < N; i++) {
			for (int j = 0; j < K; j++) {
				dx = points[i][0] - centers[j][0];
				dy = points[i][0] - centers[j][1];
				distances[i][j] = dx * dx + dy * dy;
			}
			min = distances[i][0];
			kinds[i] = 0;
			for (int j = 1; j < K; j++) {
				if (distances[i][j] < min) {
					min = distances[i][j];
					kinds[i] = j;
				}
			}
		}
	}

	void calcCenters() {
		for (int j = 0; j < K; j++) {
			centers[j][0] = 0;
			centers[j][1] = 0;
			int count = 0;
			for (int i = 0; i < N; i++) {
				if (kinds[i] == j) {
					centers[j][0] += points[i][0];
					centers[j][1] += points[i][1];
					count++;
				}
			}
			centers[j][0] /= count;
			centers[j][1] /= count;
		}
	}

	void initUI() {
		win = new JFrame("K-Means");
		win.setSize(WIN_WIDTH, WIN_HEIGHT);
		win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		win.setResizable(false);
		win.setVisible(true);
	}

	void plot() {
		Graphics g = win.getGraphics();
		g.clearRect(0, 0, WIN_WIDTH, WIN_HEIGHT);
		for (int i = 0; i < N; i++) {
			g.setColor(MARKER_COLORS[kinds[i]]);
			g.drawString(MARKER_TEXTS[kinds[i]], (int) points[i][0], (int) (WIN_HEIGHT - 20 - points[i][1]));
		}
		for (int i = 0; i < K; i++) {
			g.setColor(Color.BLACK);
			g.drawString("9", (int) centers[i][0], (int) (WIN_HEIGHT - 20 - centers[i][1]));
		}
	}

	public static void main(String[] args) throws InterruptedException {
		Exp4_4 kMeans = new Exp4_4();
		kMeans.generatePoints();
		kMeans.initCenters();
		kMeans.initUI();
		for (int i = 0; i < 10; i++) {
			kMeans.plot();
			kMeans.assignPoints();
			kMeans.calcCenters();
			Thread.sleep(500);
		}
	}
}
